﻿//-----------------------------------------------------------------------
// <copyright company="www.3WayWebdesign.de">
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
//
// <author>Michael Morbach</author>
// <email>Michael@3waywebdesign.de</email>
// <web>http://www.3waywebdesign.de</web>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Timers;
using Tww.Pixxler.SharedObjects.DTO;

namespace Tww.Pixxler.PixxlerService.Domain.SessionManagement
{
    public class SessionManager
    {
        #region Fields

        private Dictionary<Guid, PixxlerSession> runningSessions;
        private int minutesToSessionTimeout;
        private Timer triggerTimer;

        #endregion

        #region Ctor

        public SessionManager( int minutesToSessionTimeout )
        {
            this.runningSessions = new Dictionary<Guid, PixxlerSession>();
            this.minutesToSessionTimeout = minutesToSessionTimeout;
            this.triggerTimer = new Timer( 60000 ); // Triggert alle 60sekunden
            this.triggerTimer.AutoReset = true;
            this.triggerTimer.Elapsed += triggerTimer_Elapsed;
            this.triggerTimer.Start();
        }



        #endregion

        private void KillAllUserSessions( Guid userID )
        {
            var killingSessions = this.runningSessions.Where( u => u.Value != null && u.Value.PixxlerUser != null && u.Value.PixxlerUser.BenutzerID == userID ).ToList();
            killingSessions.ForEach( z => this.runningSessions.Remove( z.Key ) );
        }

        #region Public Methods

        public PixxlerSession GetUserForSession( Guid sessionID )
        {
            var entry = this.runningSessions.Where( z => z.Key == sessionID ).FirstOrDefault();

            return entry.Value;
        }

        public void ExtendSession( Guid sessionID )
        {
            var session = this.runningSessions.FirstOrDefault( u => u.Key == sessionID );

            if ( session.Value != null )
            {
                session.Value.SessionStart = DateTime.Now;
            }
        }

        public void CheckForSessionTimeout()
        {
            var timeOuts = this.runningSessions.Where( u => u.Value != null && u.Value.SessionStart.AddMinutes( this.minutesToSessionTimeout ) <= DateTime.Now ).ToList();
            timeOuts.ForEach( u => runningSessions.Remove( u.Key ) );
        }

        public bool CheckSessionValid( Guid sessionID )
        {
            return this.runningSessions.Any( z => z.Key == sessionID );
        }

        public void LogOff( Guid sessionID )
        {
            if ( CheckSessionValid( sessionID ) )
            {
                this.runningSessions.Remove( sessionID );
            }
        }

        public Guid Login( PixxlerUserDTO user )
        {
            // Alle vorherigen Sessions entfernen
            this.KillAllUserSessions( user.BenutzerID );

            var newSessionID = Guid.NewGuid();
            this.runningSessions.Add( newSessionID, new PixxlerSession() { PixxlerUser = user, SessionID = newSessionID, SessionStart = DateTime.Now } );

            return newSessionID;
        }

        #endregion

        #region Eventhandling

        void triggerTimer_Elapsed( object sender, ElapsedEventArgs e )
        {
            this.CheckForSessionTimeout();
        }

        #endregion
    }
}